package utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;

/**
 * 交易记录信息头，32 bytes
 * * int = 4 bytes
 * * 为了简便，小于4 bytes 的也用int表示
 *
 * @author likai
 * @date 2018/09/05
 */
public class TradeHeader {
    /**
     * 保留字段,2 bytes
     */
    private byte[] reservations = new byte[2];

    /**
     * 终端设备编号, 4 bytes
     */
    private int deviceNumber;

    /**
     * 采集日期, 4 bytes
     */
    private LocalDate gatherDate;

    /**
     * 采集时间, 3 bytes
     */
    private LocalTime gatherTime;

    /**
     * 交易记录类型，1 byte
     */
    private int tradeType;

    /**
     * 文件后缀名 4 bytes
     */
    private String fileSuffix;

    /**
     * 文件长度  4 bytes, 128 * n,
     */
    private int recordNumber;


    /**
     * 消费金额, 3 bytes
     */
    private int consumeAccount;

    /**
     * 消费笔数, 2 bytes
     */
    private int cousumeNumber;

    /**
     * 全免金额, 2 bytes
     */
    private int freeNumber;

    /**
     * 城市代码, 2 bytes
     */
    private int cityCode;

    /**
     * 交易文件版本, 1 byte
     */
    private int tradeFileVersion;


    public InputStream getFile() {
        return file;
    }

    public void setFile(InputStream file) {
        this.file = file;
    }

    private InputStream file;


    public void parse() {
        byte[] bytes = new byte[32];
        try {
            file.read(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }

        /**
         * 保留字段,2 byte
         */
        this.reservations = Arrays.copyOfRange(bytes, 0, 2);

        /**
         * 终端设备编号, 4 byte
         */
        byte[] deviceNumberArray = Arrays.copyOfRange(bytes, 2, 6);
        this.deviceNumber = java.nio.ByteBuffer.wrap(deviceNumberArray).order(java.nio.ByteOrder.LITTLE_ENDIAN).getInt();

        /**
         * 采集日期, 4 byte, 格式YYYYMMDD
         */
        byte[] gatherDateArray = Arrays.copyOfRange(bytes, 6, 10);
        String gatherDateStr = BCD.BCDtoString(gatherDateArray);
        gatherDate = LocalDate.parse(gatherDateStr, DateTimeFormatter.BASIC_ISO_DATE);

        /**
         * 采集时间, 3 byte
         */
        byte[] gatherTimeArray = Arrays.copyOfRange(bytes, 10, 13);
        String gatherTimeStr = BCD.BCDtoString(gatherTimeArray);
        gatherTime = LocalTime.parse(gatherTimeStr, DateTimeFormatter.ofPattern("HHmmss"));

        /**
         * 交易记录类型，1 byte
         */
        Byte tradeType = bytes[13];
        this.tradeType = tradeType.intValue();


        /**
         * 文件后缀名, 4 byte
         */
        byte[] fileSuffixArray = Arrays.copyOfRange(bytes, 14, 18);
        try {
            this.fileSuffix = new String(fileSuffixArray, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        /**
         * 文件长度 128 * n, 4 byte
         */
        byte[] recordNumberArray = Arrays.copyOfRange(bytes, 18, 22);
        this.recordNumber = java.nio.ByteBuffer.wrap(recordNumberArray).order(java.nio.ByteOrder.LITTLE_ENDIAN).getInt();
        this.recordNumber = this.recordNumber / 128;

        /**
         * 消费金额, 3 byte
         */
        byte[] consumeAccountArray = Arrays.copyOfRange(bytes, 22, 25);
        byte b3 = consumeAccountArray[2];
        byte b2 = consumeAccountArray[1];
        byte b1 = consumeAccountArray[0];
        this.consumeAccount = (b3 & 0xFF) | ((b2 & 0xFF) << 8) | ((b1 & 0x0F) << 16);

        /**
         * 消费笔数, 2 byte
         */
        byte[] cousumeNumberArray = Arrays.copyOfRange(bytes, 25, 27);
        this.cousumeNumber = java.nio.ByteBuffer.wrap(cousumeNumberArray).order(java.nio.ByteOrder.LITTLE_ENDIAN).getChar();

        /**
         * 全免金额, 2 byte
         */
        byte[] freeNumberArray = Arrays.copyOfRange(bytes, 27, 29);
        this.freeNumber = java.nio.ByteBuffer.wrap(freeNumberArray).order(java.nio.ByteOrder.LITTLE_ENDIAN).getChar();

        /**
         * 城市代码, 2 byte
         */
        byte[] cityCodeArray = Arrays.copyOfRange(bytes, 29, 31);
        this.cityCode = java.nio.ByteBuffer.wrap(cityCodeArray).order(java.nio.ByteOrder.LITTLE_ENDIAN).getChar();

        /**
         * 交易文件版本, 1 byte
         */
        Byte tradeFileVersion = bytes[31];
        this.tradeFileVersion = tradeFileVersion.intValue();

    }

    public byte[] getReservations() {
        return reservations;
    }

    public void setReservations(byte[] reservations) {
        this.reservations = reservations;
    }

    public int getDeviceNumber() {
        return deviceNumber;
    }

    public void setDeviceNumber(int deviceNumber) {
        this.deviceNumber = deviceNumber;
    }

    public LocalDate getGatherDate() {
        return gatherDate;
    }

    public void setGatherDate(LocalDate gatherDate) {
        this.gatherDate = gatherDate;
    }

    public LocalTime getGatherTime() {
        return gatherTime;
    }

    public void setGatherTime(LocalTime gatherTime) {
        this.gatherTime = gatherTime;
    }

    public int getTradeType() {
        return tradeType;
    }

    public void setTradeType(int tradeType) {
        this.tradeType = tradeType;
    }

    public String getFileSuffix() {
        return fileSuffix;
    }

    public void setFileSuffix(String fileSuffix) {
        this.fileSuffix = fileSuffix;
    }

    public int getRecordNumber() {
        return recordNumber;
    }

    public void setRecordNumber(int recordNumber) {
        this.recordNumber = recordNumber;
    }

    public int getConsumeAccount() {
        return consumeAccount;
    }

    public void setConsumeAccount(int consumeAccount) {
        this.consumeAccount = consumeAccount;
    }

    public int getCousumeNumber() {
        return cousumeNumber;
    }

    public void setCousumeNumber(int cousumeNumber) {
        this.cousumeNumber = cousumeNumber;
    }

    public int getFreeNumber() {
        return freeNumber;
    }

    public void setFreeNumber(int freeNumber) {
        this.freeNumber = freeNumber;
    }

    public int getCityCode() {
        return cityCode;
    }

    public void setCityCode(int cityCode) {
        this.cityCode = cityCode;
    }

    public int getTradeFileVersion() {
        return tradeFileVersion;
    }

    public void setTradeFileVersion(int tradeFileVersion) {
        this.tradeFileVersion = tradeFileVersion;
    }
}
